#include <GL/glut.h>
#include <stdlib.h>
#define MUNDO 4.0

void inicializa();
void dibuja();
void redimensiona();
void tecladoEspecial(int, int, int);
void camara();
void teclado (unsigned char, int, int);
void switchMaterial();

float rx, ry;
int opcion;

void inicializa(void) {
    GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat position[] = { 0.0, 3.0, 2.0, 0.0 };
    GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, position);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    rx = ry = 0.0;
    opcion = 1;
}

void dibuja(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


    glPushMatrix();
		camara();
		switchMaterial();
		glutSolidTeapot(2.0);
    glPopMatrix();

    glutSwapBuffers();
}

void redimensiona(int ancho, int alto) {
	float aspect;

	glViewport (0, 0, ancho, alto);
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity ();

	if (alto == 0){
		alto = 1;
	}

	aspect = (float) ancho / (float) alto;

	if (ancho <= alto) {
		glOrtho(-MUNDO, MUNDO, -MUNDO/aspect, MUNDO/aspect, -MUNDO, MUNDO);
	} else {
		glOrtho(-MUNDO * aspect, MUNDO * aspect, -MUNDO, MUNDO, -MUNDO, MUNDO);
	}
}

void tecladoEspecial(int key, int mx, int my) {
	switch(key) {
		case GLUT_KEY_UP:
			rx -= 5.0;
		break;

		case GLUT_KEY_DOWN:
			rx += 5.0;
		break;
		
		case GLUT_KEY_LEFT:
			ry += 5.0;
		break;
		
		case GLUT_KEY_RIGHT:
			ry -= 5.0;
		break;

		case GLUT_KEY_F1:
			opcion = 1;
		break;

		case GLUT_KEY_F2:
			opcion = 2;
		break;

		case GLUT_KEY_F3:
			opcion = 3;
		break;

		case GLUT_KEY_F4:
			opcion = 4;
		break;
	}
	glutPostRedisplay();
}

int main(int argc, char** argv){
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize (600, 450);
    glutCreateWindow(argv[0]);
    inicializa();
    glutReshapeFunc(redimensiona);
    glutDisplayFunc(dibuja);
    glutSpecialFunc(tecladoEspecial);
    glutKeyboardFunc(teclado);
    glutMainLoop();
    return 0;
}

void camara () {
	glRotatef(rx, 1.0, 0.0, 0.0);
	glRotatef(ry, 0.0, 1.0, 0.0);
}

void teclado (unsigned char key, int mx, int my) {
	switch (key) {
		case 27:
			exit(0);
		break;
	}

	glutPostRedisplay();
}

void switchMaterial() {
    GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat mat_ambient[] = { 1.0, 0.0, 0.0, 1.0}; //rojo
    GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 };
    GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; // blanco
    GLfloat no_shininess[] = { 0.0 };
    GLfloat low_shininess[] = { 5.0 };
    GLfloat high_shininess[] = { 100.0 };
    GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};

    switch(opcion) {
		case 1:
			glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
			glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
			glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
		break;

		case 2:
			glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
			glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
			glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
		break;

		case 3:
			glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, mat_diffuse);
			glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
			glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
		break;

		case 4:
			glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, mat_diffuse);
			glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
			glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
		break;
    }
}
